@using OpenIddict.Client;
@using System.Security.Claims;
@using System.Threading
@using System.Windows
@using static OpenIddict.Abstractions.OpenIddictExceptions
@using static OpenIddict.Abstractions.OpenIddictConstants
@inject OpenIddictClientService service;

<div style="position: fixed; top: 50%; left: 50%; transform: translate(-50%, -50%);">
    <button disabled="@IsButtonDisabled" style="font-size: large" @onclick="LoginAsync">Log in using GitHub</button>
</div>

@code
{
    private bool IsButtonDisabled;

    public async Task LoginAsync()
    {
        // Disable the login button to prevent concurrent authentication operations.
        IsButtonDisabled = true;

        try
        {
            using var source = new CancellationTokenSource(delay: TimeSpan.FromSeconds(90));

            try
            {
                // Ask OpenIddict to initiate the authentication flow (typically, by starting the system browser).
                var result = await service.ChallengeInteractivelyAsync(new()
                {
                    CancellationToken = source.Token
                });

                // Wait for the user to complete the authorization process.
                var principal = (await service.AuthenticateInteractivelyAsync(new()
                {
                    CancellationToken = source.Token,
                    Nonce = result.Nonce
                })).Principal;

                MessageBox.Show($"Welcome, {principal.FindFirst(ClaimTypes.Name)!.Value}.",
                    "Authentication successful", MessageBoxButton.OK, MessageBoxImage.Information);
            }

            catch (OperationCanceledException)
            {
                MessageBox.Show("The authentication process was aborted.",
                    "Authentication timed out", MessageBoxButton.OK, MessageBoxImage.Warning);
            }

            catch (ProtocolException exception) when (exception.Error is Errors.AccessDenied)
            {
                MessageBox.Show("The authorization was denied by the end user.",
                    "Authorization denied", MessageBoxButton.OK, MessageBoxImage.Warning);
            }

            catch
            {
                MessageBox.Show("An error occurred while trying to authenticate the user.",
                    "Authentication failed", MessageBoxButton.OK, MessageBoxImage.Error);
            }
        }

        finally
        {
            // Re-enable the login button to allow starting a new authentication operation.
            IsButtonDisabled = false;
        }
    }
}